//
//  GYBleOperationManager.m
//  LockManagement
//
//  Created by apple on 2018/7/31.
//  Copyright © 2018年 yunjiazhineng. All rights reserved.
//

#import "GYBleOperationManager.h"
#import "GYBleDataManager.h"

@interface GYBleOperationManager()<CBCentralManagerDelegate,CBPeripheralDelegate,UIAlertViewDelegate>
{
    __block BOOL     _isReconnectDevice ;//用来处理发起连接时的参数问题。因为没调用连接一次，只能返回一次连接结果。
}

#pragma mark ---centerManager
/** 中心管理者 */
@property (nonatomic, strong, readwrite) CBCentralManager *centerMnaager;

/** 连接的外围设备 */
@property (nonatomic, strong, readwrite) CBPeripheral *periphreal;

/** 当前扫描时间 */
@property (nonatomic, assign) NSTimeInterval scanTimeIntervel;

/** 蓝牙扫描到设备之后的block回调 */
@property (nonatomic, copy) blueManagerSearchDeviceBlock blueManagerSearchDeviceCallBack;

/** 当前蓝牙状态 */
@property (nonatomic, assign) CBManagerState managerState;

#pragma mark -- periphreal

/** 连接超时时间(默认5秒) */
@property (nonatomic, assign) NSTimeInterval connectTimeOut;

/** 读取RSSI值的block回调 */
@property (nonatomic, strong) blueManagerReadRSSIBlock blueManagerReadRSSICallBack;

/** 记录扫描到的设备,并且是去除重复扫描的 */
@property (nonatomic, strong) NSMutableDictionary *foundDeviceDict;

/** 保存当前的写特征 */
@property (nonatomic, strong) CBCharacteristic *currentCharacteristic;
@end
@implementation GYBleOperationManager

#pragma mark -- 初始化
static GYBleOperationManager *bleOperationManager = nil;
+ (instancetype)shareOperationManager {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        bleOperationManager = [[GYBleOperationManager alloc] init];
    });
    
    return bleOperationManager;
}

#pragma mark --- CBCentralManagerDelegate

//蓝牙状态发生改变的时候会 调用此方法
- (void)centralManagerDidUpdateState:(CBCentralManager *)central {
    
    if (central.state != self.managerState) {
        //代表蓝牙的状态发生改变
        if (self.blueManagerStateChangedCallBack) {
            self.blueManagerStateChangedCallBack(self.centerMnaager, central.state);
        }
        
        NSLog(@"系统蓝牙发生改变：之前状态：%zd ，改变后状态：%zd",self.managerState,central.state) ;
        self.managerState = central.state;
        
        //弹出警告框
        if (self.managerState == CBManagerStateUnsupported) {
            UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"提示" message:@"此设备不支持BLE4.0,请更换设备" delegate:nil cancelButtonTitle:nil otherButtonTitles:@"确定", nil];
            [alertView show];
            
        }

    }
}



#pragma mark -- 扫描

- (void)scanDeviceWithCallback:(blueManagerSearchDeviceBlock)searchDeviceCallBack {
    [self scanDeviceWithTimeInterval:self.scanTimeIntervel callBack:searchDeviceCallBack];
}

- (void)scanDeviceWithTimeInterval:(NSTimeInterval)timeInterval callBack:(blueManagerSearchDeviceBlock)searchDeviceCallBack {
    [self scanDeviceWithTimeInterval:timeInterval services:nil options:nil callBack:searchDeviceCallBack];
}

- (void)scanDeviceWithTimeInterval:(NSTimeInterval)timeInterval services:(NSArray *)service options:(NSDictionary *)options callBack:(blueManagerSearchDeviceBlock)searchDeviceCallBack {
    //1.判断蓝牙的状态
    if (self.centerMnaager.state == CBManagerStatePoweredOff ) {
        
        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"打开蓝牙允许 锁群管理 连接到配件" message:nil delegate:self cancelButtonTitle:@"设置" otherButtonTitles:@"好", nil];
        alertView.tag = 101;
        
        [alertView show];
        return;
    }else if (self.centerMnaager.state == CBManagerStatePoweredOn) {
        
        //1.每次从新扫描之后要数据
        [self.foundDeviceDict removeAllObjects];
        
        self.scanTimeIntervel = timeInterval;
        self.blueManagerSearchDeviceCallBack = searchDeviceCallBack ;
        
        //1.首先先停止扫描 (判断是否正在扫描)
        if (self.isScanning) {
            [self stopScanDevice];
        }
        
        //2.设置扫描的标志
        self.scanning = YES;
        
        NSLog(@"开始扫描设备 -- 倒计时 %0.f",timeInterval);
        kWeakSelf(self)
        [self.centerMnaager scanForPeripheralsWithServices:service options:options];
        
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(timeInterval * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            //执行超时操作
            weakself.scanning = NO;
            
            if (weakself.centerMnaager.isScanning && weakself.blueManagerSearchDeviceCallBack) {
                [weakself stopScanDevice];
                
                //通知外部  扫描超时
                weakself.blueManagerSearchDeviceCallBack(nil, searchFlagTypeFinish);
            }
        });
    }
}

- (void)stopScanDevice {
    if (self.isScanning) {
        self.scanning = NO;
    }
    
    NSLog(@"停止扫描设备....");
    [self.centerMnaager stopScan];
}

#pragma mark -- connect device

- (void)connectDevice:(CBPeripheral *)periphreal withTimeOut:(NSTimeInterval)timeOut options:(NSDictionary *)options callBack:(blueManagerConnectDeviceBlock)callBack {
    
    if (!periphreal) {
        NSLog(@"connect device is nil");
        return;
    }
    
    //赋值链接设备的回到block
    if (callBack) {
        self.blueManagerConnectDeviceCallBack = [callBack copy];
    }
    
    self.connectTimeOut = timeOut;
    _isReconnectDevice = YES;//表明正在链接状态
    
    
    //判断如果该设备是连接状态的要断开设备连接 重新连接
    if (periphreal.state == CBPeripheralStateConnected ) {
        NSLog(@"attention ! the device is readly connected !" );
        [self disConnectDevice];
    }
    
    NSLog(@"begin connect device");
    [self.centerMnaager connectPeripheral:periphreal options:options];
    
    //如果设定的时间内系统没有返回连接的结果,直接返回错误信息
//    kWeakSelf(self)
//    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(timeOut * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
//        //判断是不是在连接设备的状态
//        if (!_isReconnectDevice) {
//            return ;
//        }
//
//        NSError *error = [NSError errorWithDomain:@"connect device timeout ~~" code:-101 userInfo:nil];
//        if (self.blueManagerConnectDeviceCallBack) {
//            self.blueManagerConnectDeviceCallBack(periphreal, error, deviceConntTypeFiledTimeOut);
//        }
//
//        [weakself disConnectDevice];
//    });
}


- (void)disConnectDevice {
    if (self.periphreal.state == CBPeripheralStateConnected) {
        [self.centerMnaager cancelPeripheralConnection:self.periphreal];
    }
}

#pragma mark ---- discover characteristic

//- (void)discoverCharacteristicWithCharacteristicUUIDs:(NSArray<CBUUID *> *)uuidArray callback:(blueManagerSearchCharacteristicBlock)callback {
//
//}

//- (void)discoverDeviceServiceWithUUIDArray:(NSArray<CBUUID *> *)uuidArray callback:(blueManagerSearchDeviceServiceBlock)callback {
//
//    NSLog(@"寻找设备设备上的服务  ====%@",self.periphreal.identifier.UUIDString);
//    self.blueManagerSearchDeviceServiceCallBack = callback;
//    [self.periphreal discoverServices:uuidArray];
//}

#pragma mark -- CBCentralManagerDelegate ------->发现外围设备

//发现外围设备回调方法
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *,id> *)advertisementData RSSI:(NSNumber *)RSSI {
    
    //NSLog(@"found a device  name=====%@  identifier=======%@  RSSI=====%@      advertisementData======%@",peripheral.name,peripheral.identifier,RSSI,advertisementData);
    
    //1,.搜索到新设备 --之后调用  这里要要判断是不是重复的涉设备
    BOOL isExtend = NO;
    for (NSString *tempIdentifier in self.foundDeviceDict.allKeys) {
        if ([tempIdentifier isEqualToString:peripheral.identifier.UUIDString]) {
            isExtend = YES;
        }
    }
    
    if (!isExtend) {
        [self.foundDeviceDict setObject:peripheral forKey:peripheral.identifier.UUIDString];
        self.blueManagerSearchDeviceCallBack(peripheral, searchFlagTypeAdded);
    }
}

#pragma mark -- CBPeripheralDelegate ---> 链接设备

- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral {
    NSLog(@"connect device success =======%@ =======%@",peripheral.name,peripheral.identifier);
    
    self.periphreal = peripheral;
    self.connectType = deviceConntTypeSuccess;
    //设备状态block回调
    if (self.blueManagerConnectDeviceStateCllBack) {
        self.blueManagerConnectDeviceStateCllBack(deviceConntTypeSuccess);
    }
    
    //通知外部 蓝牙链接设备成功
    self.blueManagerConnectDeviceCallBack(peripheral, nil, deviceConntTypeSuccess);
    
    //2.取消超时应该执行发方法 (暂时不做超时功能)
    
    //3.链接设备成功之后开始扫描服务
    peripheral.delegate = self;
    [peripheral discoverServices:nil];
}

- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {
    self.periphreal = nil;
    self.connectType = deviceConntTypeDisConnect;
    
    //设备连接状态block回调
    if (self.blueManagerConnectDeviceStateCllBack) {
        self.blueManagerConnectDeviceStateCllBack(deviceConntTypeDisConnect);
    }
    
    //通知外部 蓝牙断开链接的设备
    self.blueManagerConnectDeviceCallBack(peripheral, error, deviceConntTypeDisConnect);
}

- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {
    self.periphreal = nil;
    self.connectType = deviceConntTypeFailed;
    //设备连接状态block回调
    if (self.blueManagerConnectDeviceStateCllBack) {
        self.blueManagerConnectDeviceStateCllBack(deviceConntTypeFailed);
    }
    //通知外部  链接设备失败
    self.blueManagerConnectDeviceCallBack(peripheral, error, deviceConntTypeFailed);
}

#pragma mark -- CBPeripheralDelegate ---->发现服务

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(nullable NSError *)error{
    NSLog(@"设备发现服务%@ serviceArray:%@ error:%@",peripheral.identifier,peripheral.services,error);
    
    //发现服务之后通知外部
    self.blueManagerSearchDeviceServiceCallBack(peripheral, peripheral.services, error);

}

#pragma mark -- CBPeripheralDelegate -- discover characteristic

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(nonnull CBService *)service error:(nullable NSError *)error {
    NSLog(@"发现服务上的特征=========%@",service.characteristics);
    for (CBCharacteristic *tempCharacteristic in service.characteristics) {
        if ([tempCharacteristic.UUID.UUIDString isEqualToString:BLEWriteCharacteristicUUID]) {
            self.currentCharacteristic = tempCharacteristic;
//            NSData *data = [GYBleDataManager bindBleKey];
//            [peripheral writeValue:data forCharacteristic:tempCharacteristic type:CBCharacteristicWriteWithResponse];
        }
        if ([tempCharacteristic.UUID.UUIDString isEqualToString:BLEReadCharacteristicUUID]) {
            [peripheral setNotifyValue:YES forCharacteristic:tempCharacteristic];
        }
    }
    
    //通知外部
    //self.blueManagerSearchCharacteristicCallBack(peripheral, service.characteristics, error);
}

- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
    //NSLog(@"characteristic.value =======%@",characteristic.value);
        //self.blueManagerCharacteristicReturnDataCallBack(characteristic, characteristic.value);
    if ([characteristic.UUID.UUIDString isEqualToString:BLEReadCharacteristicUUID]) {
        [[NSNotificationCenter defaultCenter]postNotificationName:BLEReceeiveMessage object:characteristic.value];
        //NSLog(@"bluetooth return data =======%@",characteristic.value);
    }
}
#pragma mark -- CBPeripheralDelegate-----> update RSSI 值

//ios 8.0 的时候
- (void)peripheralDidUpdateRSSI:(CBPeripheral *)peripheral error:(nullable NSError *)error {
    //去掉警告
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
    NSLog(@"读取RSSI===========%@  RSSI=====%@  error=======%@",peripheral.identifier,peripheral.RSSI,error);
    if (self.blueManagerReadRSSICallBack) {
        self.blueManagerReadRSSICallBack(peripheral, peripheral.RSSI, error);
    }
#pragma clang diagnostic pop
}

- (void)peripheral:(CBPeripheral *)peripheral didReadRSSI:(NSNumber *)RSSI error:(NSError *)error {
    NSLog(@"读取RSSI===========%@  RSSI=====%@  error=======%@",peripheral.identifier,RSSI,error);
    if (self.blueManagerReadRSSICallBack) {
        self.blueManagerReadRSSICallBack(peripheral, RSSI, error);
    }
}

#pragma mark -- get方法


#pragma mark -- UIAlertViewDelegate

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
    switch (alertView.tag) {
        case 101:
        {
            if (buttonIndex == 0) {
                NSURL *url = [NSURL URLWithString:SystemVersion < 10.0 ? @"prefs:root=Bluetooth" :  @"App-Prefs:root=Bluetooth"];
                if ([[UIApplication sharedApplication] canOpenURL:url])
                {
                    
                    [[UIApplication sharedApplication] openURL:url];
                }
            }
        }
            break;
            
        default:
            break;
    }
}




#pragma mark -- 发送命令指令

- (void)sendMessage:(NSData *)data {
    [self.periphreal writeValue:data forCharacteristic:self.currentCharacteristic type:CBCharacteristicWriteWithResponse];
}


#pragma mark -- 懒加载

- (CBCentralManager *)centerMnaager {
    if (!_centerMnaager) {
        _centerMnaager = [[CBCentralManager alloc] initWithDelegate:self queue:dispatch_get_main_queue()];
        self.scanTimeIntervel = LONG_MAX;
    }
    return _centerMnaager;
}

- (NSMutableDictionary *)foundDeviceDict {
    if (!_foundDeviceDict) {
        _foundDeviceDict = [NSMutableDictionary dictionary];
    }
    
    return _foundDeviceDict;
}
@end
